/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.anniversary.service.impl;

import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.anniversary.domain.Teacher;
import me.zhengjie.modules.anniversary.repository.DepartmentRepository;
import me.zhengjie.modules.anniversary.repository.TeacherRepository;
import me.zhengjie.modules.anniversary.service.TeacherService;
import me.zhengjie.modules.anniversary.service.dto.TeacherDto;
import me.zhengjie.modules.anniversary.service.dto.TeacherQueryCriteria;
import me.zhengjie.modules.anniversary.service.mapstruct.TeacherMapper;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.repository.DeptRepository;
import me.zhengjie.modules.system.repository.DictDetailRepository;
import me.zhengjie.utils.*;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author Jiayin Wei
* @date 2020-07-28
**/
@Service
@RequiredArgsConstructor
public class TeacherServiceImpl implements TeacherService {

    private final TeacherRepository teacherRepository;
    private final TeacherMapper teacherMapper;
    //字典（用于查询民族）
    private final DictDetailRepository dictDetailRepository;
    //学院、专业
    private final DepartmentRepository departmentRepository;
    //行政部门
    private final DeptRepository deptRepository;
    @Override
    public Map<String,Object> queryAll(TeacherQueryCriteria criteria, Pageable pageable){
        Page<Teacher> page = teacherRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(teacherMapper::toDto));
    }

    @Override
    public List<TeacherDto> queryAll(TeacherQueryCriteria criteria){
        return teacherMapper.toDto(teacherRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public TeacherDto findById(Long id) {
        Teacher teacher = teacherRepository.findById(id).orElseGet(Teacher::new);
        ValidationUtil.isNull(teacher.getId(),"Teacher","id",id);
        return teacherMapper.toDto(teacher);
    }

    @Override
    @Transactional
    public TeacherDto findByUserId(Long userId) {
        Teacher teacher = teacherRepository.findByUserId(userId);
        if(teacher == null)
            return null;

        return teacherMapper.toDto(teacher);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeacherDto create(Teacher resources) {
        return teacherMapper.toDto(teacherRepository.save(resources));
    }

    @Override
    public Map<String, Object> batchImport(MultipartFile multipartFile, HttpServletResponse response) throws IOException {
        String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        if (multipartFile.isEmpty()) {
            throw new BadRequestException("文件为空,请重新上传");
        } else if(!Lists.newArrayList("xls","xlsx").contains(suffix)){
            throw new BadRequestException("只能上传后缀是xlsx或xls的文件,请重新上传");
        }
        File file = FileUtil.toFile(multipartFile);
        ExcelReader reader = ExcelUtil.getReader(file);
        String excelHead[]={"姓名","性别","出生年月","民族","政治面貌","身份证号码","目前所从事行业","工作单位","目前是否在贵州民大工作","行政部门","职称","职务","入职年月","联系电话","QQ号","微信号","简介"};
        String[] excelHeadAlias={ "name","gender","birthDate","nation","political","idCardNo","industry","workUnit","inGzmu","deptName","postitional","job","workDate","phone","qq","weixin","brief"};
        for (int i=0;i<excelHead.length;i++){
            reader.addHeaderAlias(excelHead[i],excelHeadAlias[i]);
        }
        List<Map<String, Object>> list = reader.readAll();
        reader.close();
        //保存教职工：先验证，对导入的数据进行校验,记录正确数据和错误数据，并将正确的数据插入数据库
        List<ExcelRowModel> listError = new ArrayList<>();//保存提示的错误信息
        list.stream().forEach(teacher ->{
            ExcelRowModel rowModel =new ExcelRowModel();
            Teacher oKteacher = ParseToTeacher(teacher, rowModel);
            if (rowModel.isValidated()){
                //添加错误的学生对象
                listError.add(rowModel);
            }else{
                //保存正确数据到数据库
                try {
                    teacherRepository.save(oKteacher);
                }catch (Exception ex) {
                    rowModel.getCells().put("error","保存该行数据失败："+ex.getMessage());
                    listError.add(rowModel);
                }
            }
        });
        //保存失败、错误学生信息不为空的时候 提供下载
        Map map =new HashMap();
        map.put("sum",list.size());
        if(listError.size()!=0) {
            List<Map<String, Object>> listError1 = teacherViewErrorDownload(listError);
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
            String nowStr =format.format(date)+ "-";
            String fileName =nowStr + "教职工错误信息." + suffix;
            String pathAndName="C:\\eladmin\\upload\\文档\\"+fileName;
            BigExcelWriter writer= ExcelUtil.getBigWriter(pathAndName);
            // 设置Excel字体样式
            writer.write(listError1);
            Font font = writer.createFont();
            font.setColor(Font.COLOR_RED);
            //第二个参数表示是否忽略头部样式
            writer.getStyleSet().setFont(font, true);
            //关闭writer，释放内存
            writer.close();
            map.put("fileName",fileName);
            map.put("errorNum",listError.size());
        }else {
            map.put("success","ok");
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Teacher resources) {
        Teacher teacher = teacherRepository.findById(resources.getId()).orElseGet(Teacher::new);
        ValidationUtil.isNull( teacher.getId(),"Teacher","id",resources.getId());
        teacher.copy(resources);
        teacherRepository.save(teacher);
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            teacherRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<TeacherDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TeacherDto teacher : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("用户ID", teacher.getUserId());
            map.put("名称", teacher.getName());
            map.put("性别", teacher.getGender());
            map.put("出生年月", teacher.getBirthDate());
            map.put("入职年月", teacher.getWorkDate());
            map.put("民族ID", teacher.getNationId());
            map.put("政治面貌ID", teacher.getPoliticalId());
            map.put("职称", teacher.getPostitional());
            map.put("职务", teacher.getJob());
            map.put("目前是否在贵州民大工作", teacher.getInGzmu());
            map.put("行政部门ID", teacher.getDeptId());
            map.put("目前所从事行业", teacher.getIndustry());
            map.put("工作单位", teacher.getWorkUnit());
            map.put("身份证号码", teacher.getIdCardNo());
            map.put("联系电话", teacher.getPhone());
            map.put("QQ号", teacher.getQq());
            map.put("微信号", teacher.getWeixin());
            map.put("简介", teacher.getBrief());
            map.put("认证状态（0：未认证，1：已认证）", teacher.getVerifyStatus());
            map.put("创建者名称", teacher.getCreateBy());
            map.put("创建时间", teacher.getCreateTime());
            map.put("修改者名称", teacher.getUpdatedBy());
            map.put("修改时间", teacher.getUpdateTime());
            map.put("排序", teacher.getSort());
            map.put("备注", teacher.getRemark());
            map.put("是否启用", teacher.getIsEnable());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Teacher findByNameAndPhone(String name, String phone) {
        return teacherRepository.findByNameAndPhone(name, phone);
    }
    /**
     * map 转换为教师对象
     * @param teacher map
     * @param rowModel 返回转换的信息
     * @return
     */
    private Teacher ParseToTeacher(Map<String, Object> teacher, ExcelRowModel rowModel ){
        //正确的教职工信息
        Teacher oKteacher=new Teacher();
        String errorMsg="";
        //姓名
        if(teacher.get("name")==null || teacher.get("name")==""){
            rowModel.setValidated(true);
            teacher.put("name","");
            errorMsg="教师姓名不能为空 ";
        }else{
            oKteacher.setName(teacher.get("name").toString().trim());
        }
        if(teacher.get("gender").equals("男")) {
            oKteacher.setGender(0);
        }else if(teacher.get("gender").equals("女")) {
            oKteacher.setGender(1);
        }else{//未知
            oKteacher.setGender(2);
        }
        //民族
        if(!StringUtils.isEmpty(teacher.get("nation").toString())) {
            DictDetail nationId = dictDetailRepository.findNation(teacher.get("nation").toString());
            oKteacher.setNationId(Long.parseLong(nationId.getValue()));
        }else{
            oKteacher.setNationId(null);
        }
        //政治面貌
        if(!StringUtils.isEmpty(teacher.get("political").toString())) {
            DictDetail politicalId = dictDetailRepository.findPolitical(teacher.get("political").toString());
            oKteacher.setPoliticalId(Long.parseLong(politicalId.getValue()));
        }else{
            oKteacher.setPoliticalId(null);
        }
        //目前是否在贵州民大工作
        if(!StringUtils.isEmpty(teacher.get("inGzmu").toString())){
            if(teacher.get("inGzmu").equals("是")) {
                oKteacher.setInGzmu("1");
            }else if(teacher.get("inGzmu").equals("否")) {
                oKteacher.setInGzmu("0");
            }
        }
        //行政部门
        if((!StringUtils.isEmpty(teacher.get("deptName").toString()))&&("1".equals(oKteacher.getInGzmu()))){
            Dept dept = deptRepository.findDeptByName(teacher.get("deptName").toString().trim());
            if(dept==null){
                rowModel.setValidated(true);
                teacher.put("deptName","");
                errorMsg=errorMsg+"该行政部门不存在";
            }else{
                oKteacher.setDeptId(dept.getId());
            }
        }
        oKteacher.setIdCardNo(StringUtils.isEmpty(teacher.get("idCardNo").toString())?null:teacher.get("idCardNo").toString());
        oKteacher.setBirthDate(StringUtils.isEmpty(teacher.get("birthDate").toString())?null:teacher.get("birthDate").toString());
        oKteacher.setIndustry(StringUtils.isEmpty(teacher.get("industry").toString())?null:teacher.get("industry").toString());
        oKteacher.setPostitional(StringUtils.isEmpty(teacher.get("postitional").toString())?null:teacher.get("postitional").toString());
        oKteacher.setWorkUnit(StringUtils.isEmpty(teacher.get("workUnit").toString())?null:teacher.get("workUnit").toString());
        oKteacher.setJob(StringUtils.isEmpty(teacher.get("job").toString())?null:teacher.get("job").toString());
        oKteacher.setWorkDate(StringUtils.isEmpty(teacher.get("workDate").toString())?null:teacher.get("workDate").toString());
        oKteacher.setPhone(StringUtils.isEmpty(teacher.get("phone").toString())?null:teacher.get("phone").toString());
        oKteacher.setQq(StringUtils.isEmpty(teacher.get("qq").toString())?null:teacher.get("qq").toString());
        oKteacher.setWeixin(StringUtils.isEmpty(teacher.get("weixin").toString())?null:teacher.get("weixin").toString());
        oKteacher.setBrief(StringUtils.isEmpty(teacher.get("brief").toString())?null:teacher.get("brief").toString());
        //认证状态 默认为待认证
        oKteacher.setVerifyStatus(0);
        //启用状态默认都是启用
        oKteacher.setIsEnable(true);
        //在excel最后一列添加错误信息提示
        teacher.put("error",errorMsg);
        //添加验证之后的学生对象信息
        rowModel.setCells(teacher);
        return oKteacher;
    }

    /**
     * 提供前端下载的错误数据
     * @param all
     * @throws IOException
     */
    public  List<Map<String, Object>> teacherViewErrorDownload(List<ExcelRowModel> all) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExcelRowModel teacher : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("姓名", teacher.getCells().get("name"));
            map.put("性别", teacher.getCells().get("gender"));
            map.put("出生年月", teacher.getCells().get("birthDate"));
            map.put("民族",  teacher.getCells().get("nation"));
            map.put("政治面貌", teacher.getCells().get("political"));
            map.put("身份证号码",teacher.getCells().get("idCardNo"));
            map.put("目前所从事行业", teacher.getCells().get("industry"));
            map.put("工作单位", teacher.getCells().get("workUnit"));
            map.put("目前是否在贵州民大工作", teacher.getCells().get("inGzmu"));
            map.put("行政部门", teacher.getCells().get("deptName"));
            map.put("职称",  teacher.getCells().get("postitional"));
            map.put("职务", teacher.getCells().get("job"));
            map.put("联系电话", teacher.getCells().get("phone"));
            map.put("QQ号", teacher.getCells().get("qq"));
            map.put("微信号",  teacher.getCells().get("weixin"));
            map.put("简介",teacher.getCells().get("brief"));
            map.put("错误信息提示",teacher.getCells().get("error"));
            list.add(map);
        }
        return list;
    }
}
